using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using NBModular.Lib.Data.Abstractions;
using NBModular.Lib.Data.Core;
using NBModular.Lib.Data.Query;
using NBModular.Lib.WeChat.Core.Auth;
using NBModular.Lib.WeChat.Core.Auth.Models;
using NBModular.Module.Admin.Domain.Account;
using NBModular.Module.WeChat.Domain.WeChat;
using NBModular.Module.WeChat.Domain.WeChat.Models;

namespace NBModular.Module.WeChat.Infrastructure.Repositories.SqlServer
{
    public class WeChatRepository : RepositoryAbstract<WeChatEntity>, IWeChatRepository
    {
        public WeChatRepository(IDbContext context) : base(context)
        {
        }

        public async Task<IList<WeChatEntity>> Query(WeChatQueryModel model)
        {
            var paging = model.Paging();

            var query = Db.Find();

			var joinQuery = query.LeftJoin<AccountEntity>((x, y) => x.CreatedBy == y.Id);
			if (!paging.OrderBy.Any())
            {
                joinQuery.OrderByDescending((x, y) => x.Id);
            }
			joinQuery.Select((x, y) => new { x, Creator = y.Name });

            var result = await joinQuery.PaginationAsync(paging);

            model.TotalCount = paging.TotalCount;

            return result;
        }

        public async Task<string> GetTokenAsync(string appid) 
        {
            var entity = await Db.Find(m => m.AppId == appid).FirstAsync();
            if (entity == null)
                return null;

            if (entity.AccessToken.NotNull()) 
            {
                var jo = entity.AccessToken.ToJObject();
                if (jo.ContainsKey("create_time")) 
                {
                    var create_time = jo["create_time"].ToDateTime();
                    if (jo.ContainsKey("expires_in"))
                    {
                        var expires_in = jo["expires_in"].ToInt() - 100;
                        if (create_time.AddSeconds(expires_in) > DateTime.Now)
                            return entity.AccessToken;
                    }
                }
            }

            WeChatAuthHelper weChatAuthHelper = new WeChatAuthHelper(); 
            string token_data = await weChatAuthHelper.GetTokenAsync(entity.AppId, entity.AppSecret);
            var json = token_data.ToJObject();
            if (json.ContainsKey("errcode"))
                return token_data;

            json.Add("create_time", DateTime.Now.ToString("G"));
            await Db.Find(m => m.AppId == appid).UpdateAsync(m => new WeChatEntity
            {
                AccessToken = json.ToString()
            });

            return json.ToString();
        }

        public async Task<string> GetUserInfoAsync(string appid, string code) 
        {
            var entity = await Db.Find(m => m.AppId == appid).FirstAsync();
            if (entity == null)
                return null;

            WeChatAuthHelper weChatAuthHelper = new WeChatAuthHelper();
            var data = await weChatAuthHelper.GetOauth2InfoAsync(entity.AppId, entity.AppSecret, code);
            var json = data.ToJObject();
            if (json.ContainsKey("errcode"))
                return data;

            return await weChatAuthHelper.GetUserInfoAsync((string)json["access_token"], (string)json["openid"]);
        }

        public async Task<string> GetTicketAsync(string appid, string access_token) 
        {
            var entity = await Db.Find(m => m.AppId == appid).FirstAsync();
            if (entity == null)
                return null;

            if (entity.JsApiTicket.NotNull())
            {
                var jo = entity.JsApiTicket.ToJObject();
                if (jo.ContainsKey("create_time"))
                {
                    var create_time = jo["create_time"].ToDateTime();
                    if (jo.ContainsKey("expires_in"))
                    {
                        var expires_in = jo["expires_in"].ToInt() - 100;
                        if (create_time.AddSeconds(expires_in) > DateTime.Now)
                            return entity.JsApiTicket;
                    }
                }
            }

            WeChatAuthHelper weChatAuthHelper = new WeChatAuthHelper();
            string ticket_data = await weChatAuthHelper.GetTicketAsync(access_token);
            var json = ticket_data.ToJObject();
            if (json.ContainsKey("errcode") && (int)json["errcode"] != 0)
                return ticket_data;

            json.Add("create_time", DateTime.Now.ToString("G"));
            await Db.Find(m => m.AppId == appid).UpdateAsync(m => new WeChatEntity
            {
                JsApiTicket = json.ToString()
            });

            return json.ToString();
        }

        public async Task<WxConfigModel> GetWxConfigAsync(string appId, string jsapi_ticket, string url)
        {
            WeChatAuthHelper weChatAuthHelper = new WeChatAuthHelper();
            return await weChatAuthHelper.GetWxConfigAsync(appId, jsapi_ticket, url);
        }
    }
}
